#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>

struct packet
{
    int len; //包体的实际字节数
    char buf[1024];
};
ssize_t readn(int fd, void *buf, size_t count)
{
    size_t nleft = count; //剩余的字节数
    size_t nread;         //已经读取的字节数

    char *bufp = (char *)buf;
    //因为不能够保证一次能够读到多少字节，所以循环读取，直到读完
    while (nleft > 0)
    {
        if ((nread = read(fd, bufp, nleft)) < 0)
        {
            if (errno == EINTR) //被信号中断，不认为出错
            {
                continue;
            }
            else
                return -1;
        }
        else if (nread == 0)
        {
            return count - nleft; //已经读取的字节数
        }

        bufp += nread;
        nleft -= nread;
    }
    return count;
}
ssize_t writen(int fd, const void *buf, size_t count)
{
    size_t nleft = count;
    size_t nwritten;

    char *bufp = (char *)buf;

    while (nleft > 0)
    {
        if ((nwritten = write(fd, bufp, nleft)) < 0)
        {
            if (errno == EINTR) //被信号中断，不认为出错
            {
                continue;
            }
            else
                return -1;
        }
        else if (nwritten == 0)
        {
            continue;
        }
        bufp += nwritten;
        nleft -= nwritten;
    }
    return count;
}
int main()
{
    int sockfd = socket(PF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket:");
        exit(1);
    }

    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    servaddr.sin_port = htons(5188);

    if ((connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr))) < 0)
    {
        perror("connect:");
        exit(1);
    }

    struct packet sendbuf;
    struct packet recvbuf;
    memset(sendbuf.buf, 0, sizeof(sendbuf));
    memset(recvbuf.buf, 0, sizeof(recvbuf));
    int n; //保存包体的长度
    printf("client send to serivce:");
    //客户端接收键盘数据放到sendbuf.buf
    while (fgets(sendbuf.buf, sizeof(sendbuf.buf), stdin) != NULL)
    {
        n = strlen(sendbuf.buf);
        sendbuf.len = htonl(n);
        writen(sockfd, &sendbuf, 4 + n);         //客户端的数据发送给服务端

        int sz = readn(sockfd, &recvbuf.len, 4); //客户端读取服务端发送过来的数据
        if (sz < -1)
        {
            perror("readn");
            exit(1);
        }
        else if (sz < 4)
        {
            printf("peer close\n");
            break;
        }
        //服务器接收客户端发来的数据,后接收包体
        n = ntohl(recvbuf.len);
        sz = readn(sockfd, recvbuf.buf, n);
        if (sz < -1)
        {
            perror("readn");
            exit(1);
        }
        else if (sz < n)
        {
            printf("peer close\n");
            break;
        }
        fputs(recvbuf.buf, stdout); //客户端打印服务端回射的数据
        memset(sendbuf.buf, 0, sizeof(sendbuf));
        memset(recvbuf.buf, 0, sizeof(recvbuf));
        printf("client send to serivce:");
    }
    close(sockfd);

    return 0;
}